home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 April: Mac OS SDK / Dev.CD Apr 98 SDK1.toast / Development Kits (Disc 1) / AIAT 1.0.1 / Examples / Sources / PPAsyncHFSStore / PPAsyncHFSStoreStream.cp next >
Encoding:
Text File  |  1997-09-11  |  4.2 KB  |  144 lines  |  [TEXT/CWIE]

  1. // PPAsyncHFSStoreStream.cp
  2. // Implements IAStoreStream for asynchronous access to an Macintosh HFS file.
  3. // Written by Blake Ward, User Experience Research, Apple Labs, Apple Computer, Inc.
  4.  
  5.  
  6. #include "PPAsyncHFSStoreStream.h"
  7. #include <string.h>
  8. #include <Errors.h>
  9. #include <Files.h>
  10.  
  11. #include <LThread.h>
  12.  
  13. #include "IAStorage.h"
  14.  
  15.  
  16. IAStorage* MakePPAsyncHFSStorage(short vRef, long dirId, const StringPtr name, OSType c, OSType t) {
  17.     return IAMakeStorage(new PPAsyncHFSStoreStream(vRef, dirId, name, c, t));
  18. }
  19.  
  20.  
  21.  
  22.  
  23. PPAsyncHFSStoreStream::PPAsyncHFSStoreStream(short v, long d, const StringPtr n, OSType c, OSType t)
  24.     : HFSStoreStream(v,d,n,c,t) 
  25. {
  26. }
  27.  
  28.  
  29.  
  30. PPAsyncHFSStoreStream::PPAsyncHFSStoreStream(short v, long d, const StringPtr n, OSType c, OSType t, bool o, bool w, short f)
  31.     : HFSStoreStream(v,d,n,c,t,o,w,f) {
  32. }
  33.  
  34.  
  35.  
  36.  
  37. IAStoreStream* PPAsyncHFSStoreStream::Clone() {
  38.     return new PPAsyncHFSStoreStream(vRefNum, dirID, fileName, creator, fileType, isOpen, isWritable, fRefNum);
  39. }
  40.  
  41.  
  42.  
  43.  
  44.  
  45. void PPAsyncHFSStoreStream::Write(uint32 address, const byte* data, uint32 length) {
  46.     OSErr err;
  47.     SThreadParamBlk    asyncPBlock;
  48.     EventRecord theEvent;
  49.     LThread *thrd;
  50.  
  51.     IAThrowIfNot(isOpen, StoreError);
  52.  
  53.     asyncPBlock.ioPB.F.ioParam.ioRefNum = fRefNum;
  54.     asyncPBlock.ioPB.F.ioParam.ioBuffer = (Ptr)data;
  55.     asyncPBlock.ioPB.F.ioParam.ioReqCount = length;
  56.     asyncPBlock.ioPB.F.ioParam.ioPosMode = fsFromStart;
  57.     asyncPBlock.ioPB.F.ioParam.ioPosOffset = address;
  58.  
  59.     // If we're currently inside a thread, then call async and suspend it
  60.     if ((thrd = LThread::GetCurrentThread()) != nil && !LThread::InMainThread()) {
  61.         // Only Yield if there are other threads ready to do something
  62.         if (LThread::CountReadyThreads() > 1) {
  63.             thrd->SetupAsynchronousResume(&asyncPBlock);
  64.             err = ::PBWriteAsync(&asyncPBlock.ioPB.F);
  65.             // Note that this call doesn't necessarily yield any time depending on
  66.             // whether the write was immediately cached.
  67.             err = thrd->SuspendUntilAsyncResume(&asyncPBlock);
  68.             }
  69.         else {
  70.             asyncPBlock.ioPB.F.ioParam.ioCompletion = nil;
  71.             err = ::PBWriteSync(&asyncPBlock.ioPB.F);
  72.             }
  73.         // In any case, if user events are pending, then give the main thread a chance
  74.         // to process user I/O.  For some reason, EventAvail doesn't detect mouseDown
  75.         // events for us.
  76.         if (::EventAvail(everyEvent, &theEvent) || ::Button())
  77.             thrd->Yield();
  78.     }
  79.     else {
  80.         asyncPBlock.ioPB.F.ioParam.ioCompletion = nil;
  81.         err = ::PBWriteSync(&asyncPBlock.ioPB.F);
  82.     }
  83.  
  84.     IAThrowIf(err, StoreError);
  85.     IAAssert(asyncPBlock.ioPB.F.ioParam.ioActCount = length);
  86. }
  87.  
  88.  
  89.  
  90.  
  91. uint32
  92. PPAsyncHFSStoreStream::Read(uint32 address, byte* data,  uint32 length) {
  93.     OSErr err;
  94.     SThreadParamBlk    asyncPBlock;
  95.     EventRecord theEvent;
  96.     LThread *thrd;
  97.  
  98.     IAThrowIfNot(isOpen, StoreError);
  99.  
  100.     asyncPBlock.ioPB.F.ioParam.ioRefNum = fRefNum;
  101.     asyncPBlock.ioPB.F.ioParam.ioBuffer = (Ptr)data;
  102.     asyncPBlock.ioPB.F.ioParam.ioReqCount = length;
  103.     asyncPBlock.ioPB.F.ioParam.ioPosMode = fsFromStart;
  104.     asyncPBlock.ioPB.F.ioParam.ioPosOffset = address;
  105.  
  106.     // If we're currently inside a thread, then call async and suspend it
  107.     if ((thrd = LThread::GetCurrentThread()) != nil && !LThread::InMainThread()) {
  108.         // Only Yield if there are other threads ready to do something
  109.         if (LThread::CountReadyThreads() > 1) {
  110.             thrd->SetupAsynchronousResume(&asyncPBlock);
  111.             err = ::PBReadAsync(&asyncPBlock.ioPB.F);
  112.             // Note that this call doesn't necessarily yield any time depending on
  113.             // whether the read was from the disk cache.
  114.             err = thrd->SuspendUntilAsyncResume(&asyncPBlock);
  115.         }
  116.         else {
  117.             asyncPBlock.ioPB.F.ioParam.ioCompletion = nil;
  118.             err = ::PBReadSync(&asyncPBlock.ioPB.F);
  119.         }
  120.         // In any case, if user events are pending, then give the main thread a chance
  121.         // to process user I/O.  For some reason, EventAvail doesn't detect mouseDown
  122.         // events for us.
  123.         if (::EventAvail(everyEvent, &theEvent) || ::Button())
  124.             thrd->Yield();
  125.     }
  126.     else {
  127.         asyncPBlock.ioPB.F.ioParam.ioCompletion = nil;
  128.         err = ::PBReadSync(&asyncPBlock.ioPB.F);
  129.     }
  130.  
  131.     IAThrowIf(err && err != eofErr, StoreError);
  132.     return asyncPBlock.ioPB.F.ioParam.ioActCount;
  133. }
  134.  
  135.  
  136. // This handy method is missing from HFSStoreStream
  137. void PPAsyncHFSStoreStream::GetFSSpec(FSSpec *fileSpec)
  138. {
  139.     fileSpec->parID = dirID;
  140.     fileSpec->vRefNum = vRefNum;
  141.     BlockMoveData(fileName, fileSpec->name, fileName[0] + 1);
  142. }
  143.  
  144.